﻿/*
 * Rack.cs
 * 
 * Copyright (C) 2011 Elena Shishkina
 * 
 * This file is part of ServerInventory.
 * 
 * ServerInventory is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ServerInventory is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ServerInventory.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace ServerInventory
{
    public class Rack: Data
    {
        public override void Process()
        {
            var mode = param("mode");
            switch (mode)
            {
                case "edit": Edit(); break;
                case "remove": Remove(); break;
                case "add": Add(); break;
                case "full": FullData(); break;
                case "list": GetList(); break;
                case "move": Move(); break;
                case "lock": LockUnit(); break;
                case "unlock": UnlockUnit(); break;
                default: LoadData(); break;
            }
        }

        private void UnlockUnit()
        {
            var rack_id = GetId();
            var unit = GetUnit();
            using (var conn = DbConnect())
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "delete from reserved_units where rack_id = @rack_id and unit = @unit";
                    cmd.Parameters.AddWithValue("@rack_id", rack_id);
                    cmd.Parameters.AddWithValue("@unit", unit);
                    cmd.ExecuteNonQuery();
                    ResultOK();
                }
            }
        }

        private void LockUnit()
        {
            var rack_id = GetId();
            var unit = GetUnit();
            using (var conn = DbConnect())
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "insert into reserved_units (rack_id, unit) values (@rack_id, @unit)";
                    cmd.Parameters.AddWithValue("@rack_id", rack_id);
                    cmd.Parameters.AddWithValue("@unit", unit);
                    cmd.ExecuteNonQuery();
                    ResultOK();
                }
            }
        }

        private void Move()
        {
            var id = GetId();
            var top = GetTop();
            var left = GetLeft();
            using (var conn = DbConnect())
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "update racks set [left] = @left, [top] = @top where id = @id";
                    cmd.Parameters.AddWithValue("@left", left);
                    cmd.Parameters.AddWithValue("@top", top);
                    cmd.Parameters.AddWithValue("@id", id);
                    cmd.ExecuteNonQuery();
                    ResultOK();
                }
            }
        }

        private void LoadData()
        {
            var dc = GetDcId();
            using (var conn = DbConnect())
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = @"select r.*, u.used_units + coalesce(',' + ru.reserved_units, ' ') as used_units, v.name as vendor 
from racks r left join vendors v on r.vendor_id = v.id 
left join
(select distinct rack_id,
(stuff((select ',' + units from inventory i2 where i1.rack_id = i2.rack_id order by units
for xml path(''), type, root).value('root[1]','nvarchar(max)'),1,1,'')) as used_units
from inventory i1) as u
on u.rack_id = r.id
left join
(select distinct rack_id,
(stuff((select ',' + cast(unit as varchar) from reserved_units u2 where u1.rack_id = u2.rack_id order by unit
for xml path(''), type, root).value('root[1]','nvarchar(max)'),1,1,'')) as reserved_units
from reserved_units u1) as ru
on ru.rack_id = r.id
where dc_id = @dc order by r.[top], r.[left]";
                    cmd.Parameters.AddWithValue("@dc", dc);
                    ToJson(cmd);
                }
            }
        }

        private void GetList()
        {
            using (var conn = DbConnect())
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "select id, dc_id, name from racks";
                    ToJson(cmd);
                }
            }
        }

        private void FullData()
        {
            using (var conn = DbConnect())
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = @"select r.*, d.name as dc, v.name as vendor
from dcs d
inner join racks r on d.id = r.dc_id
left join vendors v on v.id = r.vendor_id
order by dc, r.name";
                    ToJson(cmd);
                }
            }
        }

        private void Remove()
        {
            var id = GetId();
            using (var conn = DbConnect())
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "delete from racks where id = @id";
                    cmd.Parameters.AddWithValue("@id", id);
                    cmd.ExecuteNonQuery();
                }
                ResultOK();
            }
        }

        private void Add()
        {
            var dc_id = GetDcId();
            var units = GetUnits();
            using (var conn = DbConnect())
            {

                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "insert into racks (name, units, notes, vendor_id, dc_id, responsible) values (@name, @units, @notes, @vendor_id, @dc_id, @responsible); select @@identity;";
                    cmd.Parameters.AddWithValue("@name", param("name"));
                    cmd.Parameters.AddWithValue("@units", units);
                    cmd.Parameters.AddWithValue("@notes", param("notes"));
                    cmd.Parameters.AddWithValue("@vendor_id", ("vendor_id"));
                    cmd.Parameters.AddWithValue("@dc_id", dc_id);
                    cmd.Parameters.AddWithValue("@responsible", param("responsible"));
                    writer("{\"result\": \"RESULT_OK\", \"id\": \"" + cmd.ExecuteScalar().ToString() + "\"}");
                }
            }
        }

        private int GetId()
        {
            return GetInt("id");
        }

        private int GetDcId()
        {
            return GetInt("dc_id");
        }

        private int GetUnits()
        {
            return GetInt("units");
        }

        private int GetUnit()
        {
            return GetInt("unit");
        }

        private int GetLeft()
        {
            return GetInt("left");
        }

        private int GetTop()
        {
            return GetInt("top");
        }

        private void Edit()
        {
            var id = GetId();
            var dc_id = GetDcId();
            var units = GetUnits();

            using (var conn = DbConnect())
            {

                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "update racks set name = @name, units = @units, notes = @notes, vendor_id = @vendor_id, dc_id = @dc_id, responsible = @responsible where id = @id";
                    cmd.Parameters.AddWithValue("@name", param("name"));
                    cmd.Parameters.AddWithValue("@units", units);
                    cmd.Parameters.AddWithValue("@notes", param("notes"));
                    cmd.Parameters.AddWithValue("@vendor_id", param("vendor_id"));
                    cmd.Parameters.AddWithValue("@dc_id", dc_id);
                    cmd.Parameters.AddWithValue("@id", id);
                    cmd.Parameters.AddWithValue("@responsible", param("responsible"));
                    cmd.ExecuteNonQuery();
                    ResultOK();
                }
            }
        }

        public override void Headers(SetHeaderDelegate callback)
        {
            callback("Content-type", "application/json");
        }
    }
}